// SPDX-FileCopyrightText: Copyright 2025-2025 深圳市同心圆网络有限公司
// SPDX-License-Identifier: GPL-3.0-only

package service_impl

import (
	"context"
	"crypto/sha256"
	"crypto/sha512"
	"encoding/hex"
	"fmt"
	"hash"
	"io"
	"strings"
	"time"

	"gitcode.com/openseaotter/so_proto_gen_go.git/image_api"
	"gitcode.com/openseaotter/so_server/storage"
	"github.com/gin-gonic/gin"
)

const (
	_SECRECT_NAME_KEY = "secretname"
)

var ErrWrongDigestAlgo = fmt.Errorf("wrong digest algo")

func SetSecretUsername(c *gin.Context, username string) {
	c.Set(_SECRECT_NAME_KEY, username)
}

func GetSecretUsername(c *gin.Context) string {
	value, ok := c.Get(_SECRECT_NAME_KEY)
	if !ok {
		return ""
	}
	return value.(string)
}

func GetDigestAlgo(digest string) (string, error) {
	pos := strings.Index(digest, ":")
	if pos == -1 {
		return "", ErrWrongDigestAlgo
	}
	algo := strings.ToLower(digest[:pos])
	if algo == "sha256" || algo == "sha384" || algo == "sha512" {
		return algo, nil
	}
	return "", ErrWrongDigestAlgo
}

func GenDigest(algo string, r io.Reader) (string, error) {
	var h hash.Hash
	if algo == "sha256" {
		h = sha256.New()
	} else if algo == "sha384" {
		h = sha512.New384()
	} else if algo == "sha512" {
		h = sha512.New()
	} else {
		return "", ErrWrongDigestAlgo
	}
	buf := make([]byte, 32*1024)
	for {
		n, err := r.Read(buf)
		if n > 0 {
			h.Write(buf[:n])
		}
		if err == io.EOF {
			break
		}
		if err != nil {
			return "", err
		}
	}
	data := h.Sum(nil)
	return algo + ":" + strings.ToLower(hex.EncodeToString(data)), nil
}

func CreateImageInfo(ctx context.Context, groupName, imageName string) error {
	exist, err := storage.ImageInfoDao.Exist(ctx, groupName, imageName)
	if err != nil {
		return err
	}
	if exist {
		return nil
	}
	timeNow := time.Now().UnixMilli()
	err = storage.ImageInfoDao.Insert(ctx, &image_api.ImageInfo{
		GroupName:      groupName,
		ImageName:      imageName,
		ReferenceCount: 0,
		CreateTime:     timeNow,
		UpdateTime:     timeNow,
	})
	if err != nil {
		return err
	}
	count, err := storage.ImageInfoDao.Count(ctx, groupName)
	if err != nil {
		return err
	}
	groupInfo, err := storage.ImageGroupDao.Get(ctx, groupName)
	if err != nil {
		return err
	}
	groupInfo.ImageInfoCount = count
	groupInfo.UpdateTime = timeNow
	err = storage.ImageGroupDao.Update(ctx, groupInfo)
	if err != nil {
		return err
	}
	return nil
}
